package cloud.tianai.mate.captcha.generator.impl;

import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
import cloud.tianai.captcha.generator.ImageTransform;
import cloud.tianai.captcha.generator.common.model.dto.*;
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
import cloud.tianai.captcha.resource.common.model.dto.Resource;
import lombok.*;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import java.util.concurrent.ThreadLocalRandom;

import static cloud.tianai.mate.captcha.common.constant.MateCaptchaTypeConstant.JIGSAW;

/**
 * @Author: 天爱有情
 * @date 2022/12/30 14:06
 * @Description 拼图
 */
public class MateJigsawImageCaptchaGenerator extends AbstractImageCaptchaGenerator {

    /** 拼图矩阵. */
    @Getter
    private int[] defaultMatrix = new int[]{2, 2};

    public MateJigsawImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
        super(imageCaptchaResourceManager);
    }

    public MateJigsawImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform, CaptchaInterceptor interceptor) {
        super(imageCaptchaResourceManager);
        setImageTransform(imageTransform);
        setInterceptor(interceptor);
    }

    @Override
    protected void doInit() {
//        ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
//        // 添加一些系统的资源文件
//        resourceStore.addResource(JIGSAW, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
    }

    @Override
    @SneakyThrows
    protected void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
        // 默认拼图验证码分为4块
        int[] matrix;
        GenerateParam param = captchaExchange.getParam();
        Object matrixObj = param.getParam();
        if (matrixObj instanceof int[] && ((int[]) matrixObj).length == 2) {
            matrix = (int[]) matrixObj;
        } else {
            matrix = this.defaultMatrix;
        }
        ThreadLocalRandom random = ThreadLocalRandom.current();

        Resource imageResource = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag());
        BufferedImage image = getResourceImage(imageResource);
        // 拷贝一份图片
        BufferedImage copyImage = CaptchaImageUtils.copyImage(image, image.getType());
        int x = matrix[0];
        int y = matrix[1];
        int blockSize = x * y;
        int xBlock = image.getWidth() / x;
        int yBlock = image.getHeight() / y;
        List<Block> blockPosList = new ArrayList<>(blockSize);
        for (int i = 0; i < y; i++) {
            for (int o = 0; o < x; o++) {
                int startX = o * xBlock;
                int startY = i * yBlock;
                int endX = (o + 1) * xBlock;
                int endY = (i + 1) * yBlock;
                blockPosList.add(new Block((i * x) + o, startX, startY, endX, endY));
            }
        }
        // 随机取2个block
        ArrayList<Block> randomBlockList = new ArrayList<>(blockPosList);
        Block randomBlock1 = randomBlockList.get(random.nextInt(0, randomBlockList.size()));
        randomBlockList.remove(randomBlock1);
        Block randomBlock2 = randomBlockList.get(random.nextInt(0, randomBlockList.size()));
        // 在图上把两个随机块位置互换
        Graphics2D g2d = image.createGraphics();
        g2d.drawImage(copyImage, randomBlock1.getStartX(), randomBlock1.getStartY(), randomBlock1.getEndX(), randomBlock1.getEndY(),
                randomBlock2.getStartX(), randomBlock2.getStartY(), randomBlock2.getEndX(), randomBlock2.getEndY(), null);
        g2d.drawImage(copyImage, randomBlock2.getStartX(), randomBlock2.getStartY(), randomBlock2.getEndX(), randomBlock2.getEndY(),
                randomBlock1.getStartX(), randomBlock1.getStartY(), randomBlock1.getEndX(), randomBlock1.getEndY(), null);
        g2d.dispose();
        int[] posArr = new int[blockSize];
        for (int i = 0; i < blockSize; i++) {
            posArr[i] = i;
        }
        posArr[randomBlock1.getPos()] = randomBlock2.getPos();
        posArr[randomBlock2.getPos()] = randomBlock1.getPos();
        captchaExchange.setBackgroundImage(image);
        captchaExchange.setResourceImage(imageResource);
        JigsawData jigsawData = new JigsawData();
        jigsawData.matrix = matrix;
        jigsawData.posArr = posArr;
        captchaExchange.setTransferData(jigsawData);
//        return wrapJigsawCaptchaInfo(matrix, posArr, image, param, imageResource, data);
    }


    @Override
    public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
        BufferedImage image = captchaExchange.getBackgroundImage();
        GenerateParam param = captchaExchange.getParam();
        Resource imageResource = captchaExchange.getResourceImage();
        CustomData customData = captchaExchange.getCustomData();
        JigsawData jigsawData = (JigsawData) captchaExchange.getTransferData();
        int[] posArr = jigsawData.posArr;
        int[] matrix = jigsawData.matrix;
        ImageTransformData transform = getImageTransform().transform(param, image, imageResource, customData);

        // 将顺序转换成字符串
        StringJoiner stringJoiner = new StringJoiner(",");
        for (int i = 0; i < posArr.length; i++) {
            stringJoiner.add(String.valueOf(posArr[i]));
        }
        ImageCaptchaInfo imageCaptchaInfo = ImageCaptchaInfo.of(transform.getBackgroundImageUrl(),
                null,
                imageResource.getTag(),
                null,
                image.getWidth(),
                image.getHeight(),
                null,
                null,
                null,
                JIGSAW);
        // 矩阵数据传给前端
        customData.putViewData("matrix", matrix);
        customData.setExpand(stringJoiner.toString());
        return imageCaptchaInfo;
    }

    public void setDefaultMatrix(int x, int y) {
        if (x < 2 || y < 2) {
            throw new IllegalArgumentException("拼图验证码矩阵不能小于(2,2)");
        }
        this.defaultMatrix = new int[]{x, y};
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Block {
        private int pos;
        private int startX;
        private int startY;
        private int endX;
        private int endY;
    }

    private static class JigsawData {
        int[] matrix;
        int[] posArr;
    }

}
